/* 
 * Copyright 2010 Ziya Guven Koylu, Ozge Koylu
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at 
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package com.koylu.caffein.query.join;

import java.util.Iterator;

import com.koylu.caffein.model.caffein.CaffeinConfig;
import com.koylu.caffein.model.clazz.Clazz;
import com.koylu.caffein.model.clazz.Field;
import com.koylu.caffein.model.clazz.ForeignKey;
import com.koylu.caffein.model.clazz.Key;
import com.koylu.caffein.model.clazz.ManyToMany;
import com.koylu.caffein.model.clazz.ManyToOne;
import com.koylu.caffein.model.clazz.OneToMany;
import com.koylu.caffein.model.clazz.Relation;

public class FullJoin extends Join {

	private String on;
	private Field field;
	private String alias;
	private Clazz joinClazz;
	private StringBuffer query = null;
	
	public FullJoin() {}

	public FullJoin(String alias, String on) {
		this.alias = alias;
		this.on = on;
	}

	public String getAlias() {
		return alias;
	}
	
	public void setAlias(String alias) {
		this.alias = alias;
	}
	
	public String getOn() {
		return on;
	}
	
	public void setOn(String on) {
		this.on = on;
	}

	public Clazz getJoinClazz(CaffeinConfig caffeinConfig, Clazz clazz) throws Exception {
		if (joinClazz == null) {
			field = clazz.getChild(on);
			if(field == null){
				throw new RuntimeException("field not found:"+on+" on clazz:"+clazz.getName());
			}
			joinClazz = ((Relation) field).getForeignClazz(caffeinConfig);
		}
		return joinClazz;
	}
	
	public StringBuffer toQuery(CaffeinConfig caffeinConfig, Clazz clazz, String clazzAlias) throws Exception {
		if(query == null){
			query = new StringBuffer();
			query.append(" FULL JOIN ");
			if (field instanceof ManyToOne) {
				ManyToOne manyToOne = (ManyToOne) field;
				query.append(joinClazz.getTable()).append(" ").append(alias).append(" ON ");
				for (Iterator<ForeignKey> iterator = manyToOne.getChildren().iterator(); iterator.hasNext();) {
					ForeignKey foreignKey = iterator.next();
					query.append(clazzAlias).append(".").append(foreignKey.getColumn()).append(" = ").append(alias).append(".").append(foreignKey.getRefColumn(caffeinConfig));
					if(iterator.hasNext()){
						query.append(" AND ");
					}
				}
			} else if (field instanceof OneToMany) {
				OneToMany oneToMany = (OneToMany) field;
				query.append(joinClazz.getTable()).append(" ").append(alias).append(" ON ");
				for (Iterator<Key> iterator = oneToMany.getChildren().iterator(); iterator.hasNext();) {
					Key key = iterator.next();
					query.append(clazzAlias).append(".").append(key.getRefColumn(caffeinConfig)).append(" = ").append(alias).append(".").append(key.getColumn());
					if(iterator.hasNext()){
						query.append(" AND ");
					}
				}
			} else if (field instanceof ManyToMany) {
				ManyToMany manyToMany = (ManyToMany) field;
				String tableWithSchema = manyToMany.getTable();
				String schema = ((Clazz)manyToMany.getParent()).getSchema();
				if( schema != null && !"".equals(schema) ){
					tableWithSchema = schema+"."+manyToMany.getTable();
				}
				query.append(tableWithSchema).append(" ").append(manyToMany.getTable()).append(" ON ");
				for (Iterator<Key> iterator = manyToMany.getKeys().iterator(); iterator.hasNext();) {
					Key key = iterator.next();
					query.append(clazzAlias).append(".").append(key.getRefColumn(caffeinConfig)).append(" = ").append(manyToMany.getTable()).append(".").append(key.getColumn());
					if(iterator.hasNext()){
						query.append(" AND ");
					}
				}
				query.append(" FULL JOIN ").append(joinClazz.getTable()).append(" ").append(alias).append(" ON ");
				for (Iterator<ForeignKey> iterator = manyToMany.getForeignKeys().iterator(); iterator.hasNext();) {
					ForeignKey foreignKey = iterator.next();
					query.append(manyToMany.getTable()).append(".").append(foreignKey.getColumn()).append(" = ").append(alias).append(".").append(foreignKey.getRefColumn(caffeinConfig));
					if(iterator.hasNext()){
						query.append(" AND ");
					}
				}
			}			
		}
		return query;
	}
}